package com.yanqu.road.server.gameplayer.module.patrons;

import com.yanqu.road.dao.impl.player.UserCombLeaderDaoImpl;
import com.yanqu.road.entity.config.patrons.CombInfo;
import com.yanqu.road.entity.config.patrons.PatronsInfo;
import com.yanqu.road.entity.config.promotion.PromotionInfo;
import com.yanqu.road.entity.config.skill.SkillInfo;
import com.yanqu.road.entity.config.skill.SkillUpgradeInfo;
import com.yanqu.road.entity.enums.eGamePlayerEventType;
import com.yanqu.road.entity.enums.ePatronsSkillType;
import com.yanqu.road.entity.enums.eSkillType;
import com.yanqu.road.entity.log.LogCombLeaderChoose;
import com.yanqu.road.entity.log.LogPatronsSkillUpgrade;
import com.yanqu.road.entity.player.*;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.logic.pb.PatronsPb;
import com.yanqu.road.pb.patrons.CombLeaderProto;
import com.yanqu.road.pb.patrons.PatronsProto;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.manger.ConfigMgr;
import com.yanqu.road.server.manger.config.PatronsMgr;
import com.yanqu.road.server.manger.config.PromotionMgr;
import com.yanqu.road.server.manger.config.SkillMgr;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.manger.log.LogMgr;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.GameProtocol;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class CombLeaderModule extends GeneralModule {
    public CombLeaderModule(GamePlayer player) {
        super(player);
    }

    private Map<Integer, UserCombLeaderData> leaderDataMap = new ConcurrentHashMap<>();

    @Override
    public boolean loadData() {
        leaderDataMap = new UserCombLeaderDaoImpl().getUserCombLeaderData(getUserId());
        return true;
    }

    @Override
    public boolean afterLoadData() {
        return true;
    }

    @Override
    public boolean saveData() {
        for (UserCombLeaderData data : leaderDataMap.values()) {
            if (data.isInsertOption()) {
                new UserCombLeaderDaoImpl().add(data);
            } else if (data.isUpdateOption()) {
                new UserCombLeaderDaoImpl().update(data);
            }
        }
        return true;
    }

    public void loginSendMsg() {

    }

    public void afterLogin() {
        syncUserData();
    }

    public void syncUserData() {
        ArrayList<UserCombLeaderData> list = new ArrayList<>(leaderDataMap.values());
        if (!list.isEmpty()) {
            CombLeaderProto.CombLeaderUserDataSyncMsg.Builder syncMsg = PatronsPb.parseCombLeaderUserDataSyncMsg(list);
            player.sendPacket(GameProtocol.S_COMB_LEADER_SYNC % 20000, syncMsg);
        }
    }

    public void syncCombLeaderData(List<UserCombLeaderData> dataList) {
        CombLeaderProto.CombLeaderUserDataSyncMsg.Builder syncMsg = PatronsPb.parseCombLeaderUserDataSyncMsg(dataList);
        player.sendPacket(GameProtocol.S_COMB_LEADER_SYNC % 20000, syncMsg);
    }

    public void syncCombLeaderData(int patronsId) {
        UserCombLeaderData leaderData = getUserCombLeaderDataByPatronsId(patronsId);
        if (leaderData == null) {
            return;
        }
        CombLeaderProto.CombLeaderUserDataSyncMsg.Builder syncMsg = PatronsPb.parseCombLeaderUserDataSyncMsg(Collections.singletonList(leaderData));
        player.sendPacket(GameProtocol.S_COMB_LEADER_SYNC % 20000, syncMsg);
    }

    public int chooseLeader(int combId, int leaderId) {
        PatronsInfo patronsInfo = PatronsMgr.getPatronsInfo(leaderId);
        if (patronsInfo == null) {
            return GameErrorCode.E_PATRONS_NO_FOUND;
        }

        if (patronsInfo.getCombId() != combId) {
            return GameErrorCode.E_COMB_LEADER_NOT_YOURS;
        }

        PromotionInfo promotionInfo = PromotionMgr.getCharacterNextPromotion(combId, 0);
        if (promotionInfo == null) {
            return GameErrorCode.E_COMB_LEADER_NOT_FIND;
        }

        CombInfo combInfo = PatronsMgr.getPatronsComb(combId);
        if (combInfo == null) {
            return GameErrorCode.E_COMB_NOT_FIND;
        }

        PatronsModule patronsModule = player.getModule(PatronsModule.class);
        UserPatrons userPatrons = patronsModule.getUserPatrons(leaderId);
        if (userPatrons == null) {
            return GameErrorCode.E_PATRONS_NO_FOUND;
        }

        int oldLeaderId = 0;
        UserCombLeaderData combLeaderData = getUserCombLeaderDataByCombId(combId);
        if (combLeaderData == null) {
            combLeaderData = createNewUserCombLeaderData(combId, leaderId);
        } else {
            if (combLeaderData.getLeaderId() == leaderId) {
                return GameErrorCode.E_COMB_LEADER_ALREADY;
            }
            long currentTime = DateHelper.getCurrentTime();
            if (currentTime - combLeaderData.getLastChooseTime() < GameConfig.COMBO_LEADER_CHANGE_NEED_TIME * DateHelper.SECOND_MILLIONS) {
                return GameErrorCode.E_COMB_LEADER_CHOOSE_CD;
            }

            //转移前羁绊了这个门客,转移后要去掉
            if (combLeaderData.getKeepSakePatronsId() == userPatrons.getPatronsId()) {
                combLeaderData.setKeepSakePatronsId(0);
                combLeaderData.setKeepSakeTime(0);
            }

            oldLeaderId = combLeaderData.getLeaderId();

            combLeaderData.setLeaderId(leaderId);//更新组合首领
            combLeaderData.setLastChooseTime(DateHelper.getCurrentTime());

            userPatrons.setCombLeaderSkillList(new ArrayList<>(combLeaderData.getSkillMap().values()));//更换首领后,加入技能
            userPatrons.setLeaderPromotionId(combLeaderData.getPromoteId());
            userPatrons.setLeaderKeepSakePatronsId(combLeaderData.getKeepSakePatronsId());
        }

        if (oldLeaderId > 0) {
            UserPatrons oldUserPatrons = patronsModule.getUserPatrons(oldLeaderId);
            if (oldUserPatrons != null) {
                oldUserPatrons.setCombLeaderSkillList(new ArrayList<>());//更换首领后,旧的首领要清空技能
                oldUserPatrons.setLeaderPromotionId(0);
                oldUserPatrons.setLeaderKeepSakePatronsId(0);

                List<UserPatrons> keepSakeTargetPatronsIdPatronsList = patronsModule.getKeepSakeTargetPatronsIdPatronsList(oldLeaderId);
                for (UserPatrons patrons : keepSakeTargetPatronsIdPatronsList) {
                    if (patrons.getKeepSakePatronsId() > 0) {
                        patrons.setKeepSakePatronsId(0);
                        patrons.setKeepSakeTime(0);
                    } else {//通过魁首系统绑定的
                        UserCombLeaderData leaderData = getUserCombLeaderDataByPatronsId(patrons.getPatronsId());
                        if (leaderData != null) {
                            leaderData.setKeepSakePatronsId(0);
                            leaderData.setKeepSakeTime(0);

                            patrons.setLeaderKeepSakePatronsId(0);
                        }
                    }
                }

                patronsModule.calcTalentSkillAddition(oldUserPatrons);//要更新天赋技能
            }
        }

        patronsModule.calcTalentSkillAddition(userPatrons);//要更新天赋技能

        CombLeaderProto.CombLeaderChoseLeaderRespMsg.Builder resp = CombLeaderProto.CombLeaderChoseLeaderRespMsg.newBuilder();
        resp.setRet(0);
        resp.setCombLeader(PatronsPb.parseCombLeaderTempMsg(combLeaderData));
        player.sendPacket(GameProtocol.S_COMB_LEADER_CHOOSE_LEADER % 20000, resp);

        patronsModule.syncPatronsCache(patronsModule.getUserPatronsList());

        AutoLogMgr.add(new LogCombLeaderChoose(getUserId(), combLeaderData.getCombId(), oldLeaderId, combLeaderData.getLeaderId()));
        return 0;
    }

    public int skillUpgrade(int patronsId, int skillId, int times, int goodsIndex) {
        PatronsInfo patronsInfo = PatronsMgr.getPatronsInfo(patronsId);
        if (patronsInfo == null) {
            return GameErrorCode.E_PATRONS_NO_FOUND;
        }

        UserPatrons userPatrons = player.getModule(PatronsModule.class).getUserPatrons(patronsId);
        if (userPatrons == null) {
            return GameErrorCode.E_PATRONS_NO_FOUND;
        }

        UserCombLeaderData combLeaderData = getUserCombLeaderDataByCombId(patronsInfo.getCombId());
        if (combLeaderData != null && combLeaderData.getLeaderId() > 0 && combLeaderData.getLeaderId() != patronsId) {
            return GameErrorCode.E_COMB_LEADER_NOT_YOURS;
        }

        if (combLeaderData == null) {
            combLeaderData = createNewUserCombLeaderData(patronsInfo.getCombId(), patronsId);
        }

        if (combLeaderData.getLeaderId() == 0) {
            combLeaderData.setLeaderId(patronsId);
        }

        PromotionInfo promotionInfo = PromotionMgr.getCharacterNowPromotion(combLeaderData.getCombId(), combLeaderData.getPromoteId());
        if (promotionInfo == null) {
            promotionInfo = PromotionMgr.getCharacterNextPromotion(combLeaderData.getCombId(), combLeaderData.getPromoteId());
            if (promotionInfo == null) {
                return GameErrorCode.E_PATRONS_PROMOTE_LEVEL_MAX;
            }
        }

        if (!promotionInfo.getParamList().contains(String.valueOf(skillId)) && !promotionInfo.getSkillList().contains(skillId) && !combLeaderData.getSkillMap().containsKey(skillId)) {
            return GameErrorCode.E_NOT_COMB_LEADER_SKILL;
        }

        SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
        if (skillInfo == null) {
            return GameErrorCode.E_PATRONS_SKILL_NO_FOUND;
        }

        int skillLv = combLeaderData.getSkillLv(skillId);
        int upgradeType = skillInfo.getUpgradeType(goodsIndex);

        int maxLevel = skillInfo.getMaxLevel();
        //是否是门客信物的伴生技能
        if (ConfigMgr.getSakeCompanionParamMap().containsKey(skillInfo.getId())) {
            //看下门客有没有信物技能
            UserPatronsSkill sakeSkill = null;
            for (UserPatronsSkill skill : userPatrons.getSkillList()) {
                SkillInfo ski = SkillMgr.getSkillInfo(skill.getSkillId());
                if (ski.getType() == eSkillType.PatronsKeepSakeLinkAddtition.getValue()) {
                    sakeSkill = skill;
                    break;
                }
            }
            if (sakeSkill != null) {
                maxLevel = ConfigMgr.getPatronsCompanionSkillLvLimit(skillInfo.getId(), sakeSkill.getSkillLv(), maxLevel);
            }
        } else {
            maxLevel = getMaxLevel(skillInfo);
        }

        if (skillLv >= maxLevel) {
            return GameErrorCode.E_PATRONS_SKILL_LEVEL_MAX;
        }

        if (maxLevel > 0 && times != 1 && skillLv + times > maxLevel) {//十连升级下 如果有最大等级限制且不满十次满级 则取实际升级次数
            times = maxLevel - skillLv;
        }

        if (null == SkillMgr.getSkillUpgradeInfo(upgradeType, skillLv + times) || times < 1) {
            return GameErrorCode.E_PATRONS_SKILL_LEVEL_MAX;
        }

        //取出消耗
        SkillUpgradeInfo skillUpgradeInfo = SkillMgr.getSkillUpgradeInfo(upgradeType, skillLv);
        if (skillUpgradeInfo == null) {
            return GameErrorCode.E_PATRONS_SKILL_LEVEL_MAX;
        }

        Integer consumeId = skillInfo.getConsumeGoodsId().get(goodsIndex);
        Property consume = null;
        long needConsume;

        if (times == 1) {              //v4.5烹饪百业筹算授学经验与其他消耗统一计算
            needConsume = skillUpgradeInfo.getConsumeCount();
        } else {
            needConsume = 0;
            for (int i = 0; i < times; i++) {  //v4.5升级几次就拿后面几级需要的道具
                SkillUpgradeInfo thisGradeUpdateInfo = SkillMgr.getSkillUpgradeInfo(upgradeType, skillLv + i);
                needConsume += thisGradeUpdateInfo.getConsumeCount();
            }
        }

        //根据升级类型扣除消耗
        SkillUpgradeDeductConsumeResult result = player.getModule(PatronsModule.class).removeConsume(consumeId, needConsume, goodsIndex, skillInfo, userPatrons);
        if (result.getRet() != 0) { //不足则返回
            return result.getRet();
        }
        consume = result.getConsume();

        //升级
        combLeaderData.addSkillLv(skillId, times);

        //判断是否自动晋升
        checkAndPromote(combLeaderData);

        //检查门客信物伴生技能解锁//checkPatronsSakeAssociatedSkillUnlock(skillInfo, userPatrons, userPatronsSkill);
        if (skillInfo.getType() == eSkillType.PatronsKeepSakeLinkAddtition.getValue()) {
            List<Integer> skillList = ConfigMgr.getPatronsSakeUnlockSkillList(combLeaderData.getSkillLv(skillId));
            for (Integer checkId : skillList) {
                if (combLeaderData.getSkillLv(checkId) == 0) {
                    combLeaderData.addSkillLv(checkId, 1);
                }
            }
        }

        //更新首领技能
        userPatrons.setCombLeaderSkillList(new ArrayList<>(combLeaderData.getSkillMap().values()));
        userPatrons.setLeaderPromotionId(combLeaderData.getPromoteId());
        player.getModule(PatronsModule.class).calcTalentSkillAddition(userPatrons);//要更新天赋技能

        // 日志
        AutoLogMgr.add(new LogPatronsSkillUpgrade(player.getUserId(), patronsId, skillId, ePatronsSkillType.CombLeader.getValue(), skillLv, combLeaderData.getSkillLv(skillId), PropertyHelper.parsePropertyToString(consume)));
        //任务、成就
        player.notifyListener(eGamePlayerEventType.PatronsSkillUpgradeTimes.getValue(), times);
        player.notifyListener(eGamePlayerEventType.PatronsTypeSkillUpgradeTimes.getValue(), new UserPatronsSkillUpgradeTypeArgs(skillInfo.getType(), times));

        //基金
        if (promotionInfo.getParamList().contains(String.valueOf(skillId))) {
            player.notifyListener(eGamePlayerEventType.CombLeaderSkillLv.getValue());
        }

        CombLeaderProto.CombLeaderSkillUpgradeRespMsg.Builder resp = CombLeaderProto.CombLeaderSkillUpgradeRespMsg.newBuilder();
        resp.setRet(0);
        resp.setCombLeader(PatronsPb.parseCombLeaderTempMsg(combLeaderData));
        player.sendPacket(GameProtocol.S_COMB_LEADER_SKILL_UPGRADE % 20000, resp);

        //门客属性变更
        player.getModule(PatronsModule.class).syncPatronsCache(player.getModule(PatronsModule.class).getUserPatronsList());

        return 0;
    }

    public void checkAndPromote(UserCombLeaderData combLeaderData) {
        PromotionInfo nextPromotion = PromotionMgr.getCharacterNextPromotion(combLeaderData.getCombId(), combLeaderData.getPromoteId());
        if (nextPromotion != null) {
            boolean canPromote = true;
            Property skillNeed = PropertyHelper.parseStringToProperty(nextPromotion.getParamList());
            for (Map.Entry<Integer, BigInteger> entry : skillNeed.getGoods().entrySet()) {
                int checkId = entry.getKey();
                int checkLv = entry.getValue().intValue();

                int takeLv = combLeaderData.getSkillLv(checkId);
                if (takeLv < checkLv) {
                    canPromote = false;
                    break;
                }
            }
            if (canPromote) {
                combLeaderData.setPromoteId(nextPromotion.getId());

                //获得晋升后的技能
                for (Integer skillId : nextPromotion.getSkillList()) {
                    if (skillId == 0) {
                        continue;
                    }
                    if (combLeaderData.getSkillLv(skillId) == 0) {
                        combLeaderData.addSkillLv(skillId, 1);
                    }
                }

                for (Integer skillId : nextPromotion.getTalentList()) {
                    if (skillId == 0) {
                        continue;
                    }
                    if (combLeaderData.getSkillLv(skillId) == 0) {
                        combLeaderData.addSkillLv(skillId, 1);
                    }
                }

                UserPatrons userPatrons = player.getModule(PatronsModule.class).getUserPatrons(combLeaderData.getLeaderId());
                if (userPatrons != null) {
                    player.getModule(PatronsModule.class).calcTalentSkillAddition(userPatrons);//要更新天赋技能
                }
            }
        }
    }

    public UserCombLeaderData getUserCombLeaderDataByCombId(int combId) {
        return leaderDataMap.get(combId);
    }

    public UserCombLeaderData getUserCombLeaderDataByPatronsId(int patronsId) {
        for (UserCombLeaderData combLeaderData : leaderDataMap.values()) {
            if (combLeaderData.getLeaderId() == patronsId) {
                return combLeaderData;
            }
        }
        return null;
    }

    public Map<Integer, UserCombLeaderData> getLeaderDataMap() {
        return leaderDataMap;
    }

    private UserCombLeaderData createNewUserCombLeaderData(int combId, int patronsId) {
        UserCombLeaderData userCombLeaderData = new UserCombLeaderData(getUserId(), combId);
        userCombLeaderData.setLeaderId(patronsId);
        userCombLeaderData.setLastChooseTime(DateHelper.getCurrentTime());

        leaderDataMap.put(combId, userCombLeaderData);

        return userCombLeaderData;
    }

    public int getMaxLevel(SkillInfo skillInfo) {
        if (skillInfo == null) {
            return 0;
        }

        if (skillInfo.getType() != eSkillType.Qualification.getValue()) {
            return skillInfo.getMaxLevel();
        }

        int maxLevel = skillInfo.getMaxLevel() + player.getModule(PatronsModule.class).getSkillMaxLevelAddValue();
        return maxLevel;
    }

    public int keepSakeRelation(int patronsId, int selectPatronsId) {
        PatronsModule patronsModule = player.getModule(PatronsModule.class);
        UserPatrons userPatrons = patronsModule.getUserPatrons(patronsId);
        if (userPatrons == null) {
            return GameErrorCode.E_PATRONS_NO_FOUND;
        }
        PatronsInfo patronsInfo = PatronsMgr.getPatronsInfo(userPatrons.getPatronsId());
        if (patronsInfo == null) {
            return GameErrorCode.E_PATRONS_NO_FOUND;
        }

        UserCombLeaderData combLeaderData = getUserCombLeaderDataByCombId(patronsInfo.getCombId());
        if (combLeaderData == null) {
            return GameErrorCode.E_PATRONS_CAN_NOT_PROMOTE;
        }

        if (combLeaderData.getLeaderId() != patronsId) {
            return GameErrorCode.E_COMB_LEADER_NOT_YOURS;
        }

        PromotionInfo promotionInfo = PromotionMgr.getCharacterNowPromotion(patronsInfo.getCombId(), combLeaderData.getPromoteId());
        if (promotionInfo == null) {
            return GameErrorCode.E_PATRONS_CAN_NOT_PROMOTE;
        }

        if (selectPatronsId > 0) {
            UserPatrons selectPatrons = patronsModule.getUserPatrons(selectPatronsId);
            if (selectPatrons == null) {
                return GameErrorCode.E_PATRONS_NO_FOUND;
            }
        }

        int oldSelectPatronsId = combLeaderData.getKeepSakePatronsId();
        long now = DateHelper.getCurrentTime() / 1000;
        if (combLeaderData.getKeepSakeTime() > 0 && now - combLeaderData.getKeepSakeTime() <= GameConfig.KEEPSAKE_CD * 60) {
            return GameErrorCode.E_PATRONS_KEEP_SAKE_RELATION_CD;
        }

        if (selectPatronsId > 0) {
            //找一下选择的门客被其他门客绑定的次数
            int ret = player.getModule(PatronsModule.class).checkSelectPatronsBeSelectNum(selectPatronsId);
            if (ret > 0) {
                return ret;
            }
        }
        if (selectPatronsId > 0) {
            combLeaderData.setKeepSakeTime(now);
            combLeaderData.setKeepSakePatronsId(selectPatronsId);
        } else {
            combLeaderData.setKeepSakePatronsId(0);
        }

        userPatrons.setLeaderKeepSakePatronsId(combLeaderData.getKeepSakePatronsId());

        List<UserPatrons> changeList = new ArrayList<>();

        changeList.add(userPatrons);
        if (selectPatronsId > 0) {
            changeList.add(patronsModule.getUserPatrons(selectPatronsId));
        }

        if (oldSelectPatronsId > 0) {
            UserPatrons oldPatrons = patronsModule.getUserPatrons(oldSelectPatronsId);
            if (oldPatrons != null) {
                changeList.add(oldPatrons);
            }
        }

        PatronsProto.PatronsKeepSakeRelationAddRespMsg.Builder respMsg = PatronsProto.PatronsKeepSakeRelationAddRespMsg.newBuilder();
        respMsg.setRet(0);
        for (UserPatrons patrons : changeList) {
            PatronsProto.PatronsTempMsg.Builder patronsMsg = PatronsPb.parsePatronsTempMsg(patrons);
            if (null != patronsMsg) {
                respMsg.addPatrons(patronsMsg);
            }
        }
        player.sendPacket(Protocol.U_PATRONS_KEEP_SAKE_RELATION_ADD, respMsg);

        syncCombLeaderData(Collections.singletonList(combLeaderData));

        patronsModule.syncPatronsCache(changeList);
        return 0;
    }
}
